Repository navigation
Conversation
devnexen
reviewed
Oct 17, 2026
|
|
||
| /* PostgreSQL sends integers as an optional minus sign followed by digits. Parse that | ||
| * inline, and leave long values that might not fit into a zend_long to ZEND_ATOL(). */ | ||
| static zend_always_inline zend_long pgsql_parse_long(const char *ptr, size_t len) |
Member
There was a problem hiding this comment.
hmmm feels like "reinventing the wheel" here.
PostgreSQL sends int2/int4/int8 values in text format in canonical decimal form: an optional minus sign followed by digits without leading zeros. That is exactly what ZEND_HANDLE_NUMERIC_STR() accepts for numeric array keys, including the range check. Use it instead of calling strtoll() through ZEND_ATOL() for every value, and keep ZEND_ATOL() as fallback for anything else. fetchAll(PDO::FETCH_ASSOC) of 1M rows with 4 integer columns: -11% instructions, -9% cycles.
brainexe
force-pushed
the
perf/pdo-pgsql-inline-int-parse
branch
from
October 17, 2026 19:07
dd772c9 to
3e479d7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
After some more profiling of our heavy workload with tidewayy/perf etc in came up this optimization.
PostgreSQL sends
int2/int4/int8values in text format.pgsql_stmt_get_col()converted each of them withZEND_ATOL(), i.e.strtoll(), which handles whitespace, signs, bases and locales. In profiles of integer-heavy fetches, glibc'sstrtollaccounted for up to 10% of the CPU time.PostgreSQL always sends these in canonical decimal form: an optional minus sign followed by digits without leading zeros. That is exactly what
ZEND_HANDLE_NUMERIC_STR()accepts for numeric array keys, including the range check forzend_long. This PR uses it instead ofZEND_ATOL(), and keepsZEND_ATOL()as fallback for anything else, so the results are unchanged.A hand-written loop was about 3 percentage points faster, but reusing the existing helper avoids adding another integer parser.
is_numeric_string()only gave about 2%, because it also handles whitespace, floats and overflow to double.Benchmark
fetchAll(PDO::FETCH_ASSOC)of 1M rows with 4 integer columns, compared to master (perf stat, mean of 5 runs):Mixed workloads gain less, depending on how many columns are integers. For example,
fetchAllof 10k rows with 11 columns, 2 of them integers, executes about 2% fewer instructions.Verification
ext/pdo_pgsql/tests/fetch_integers.phpt(64-bit only) coversint2,int4andint8at their limits and around the 18/19-digit threshold, includingPHP_INT_MIN(19 digits).int2/int4/int8values with 1–19 digits, both signs and the extreme values. The fetched values and their types are identical.ext/pdoandext/pdo_pgsqltest suites pass with native prepares. With emulated prepares forced on, the same tests fail as on master.